package example;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 *
 * 　读写锁：分为读锁和写锁，多个读锁不互斥，读锁与写锁互斥，这是由jvm自己控制的，你只要上好相应的锁即可。如果你的代码只读数据，
 * 可以很多人同时读，但不能同时写，那就上读锁；如果你的代码修改数据，只能有一个人在写，且不能同时读取，那就上写锁。总之，读的时候上读锁，写的时候上写锁！
 * @author dengzhiyuan
 * @version 1.0
 * @describe
 * @time 2023/3/12 12:58
 */
public class ReentrantReadWriteLockDemo {
//    readLock()
//    该方法返回一个读锁，允许多个线程同时读取共享资源。
//    writeLock()
//    该方法返回一个写锁，只允许一个线程写入共享资源。
//    isWriteLocked()
//    该方法用于判断锁是否被写入锁定。
//    isWriteLockedByCurrentThread()
//    该方法用于判断当前线程是否持有写锁。
//    getReadLockCount()
//    该方法返回当前持有读锁的线程数量。
//    getWriteHoldCount()
//    该方法返回当前线程重入写锁的次数。
//    getReadHoldCount()
//    该方法返回当前线程重入读锁的次数。
//    getQueueLength()
//    该方法返回等待获取锁的线程数量。
//    getWaitingThreads(condition)
//    该方法返回等待在给定条件上的线程列表。
//    hasQueuedThread(thread)
//    该方法用于判断给定的线程是否在等待获取锁。
//    这些方法允许开发人员更加细粒度地控制读写锁的行为，以满足特定的需求。例如，通过getQueueLength()方法可以检查有多少线程在等待获取锁，以帮助优化并发性能。
    private Map<String, Object> map = new HashMap<String, Object>();//缓存器
    private ReadWriteLock rwl = new ReentrantReadWriteLock();
    public static void main(String[] args) {

    }
    public Object get(String id){
        Object value = null;
        rwl.readLock().lock();//首先开启读锁，从缓存中去取
        try{
            value = map.get(id);
            if(value == null){  //如果缓存中没有释放读锁，上写锁
                rwl.readLock().unlock();
                rwl.writeLock().lock();
                try{
                    if(value == null){
                        value = "aaa";  //此时可以去数据库中查找，这里简单的模拟一下
                    }
                }finally{
                    rwl.writeLock().unlock(); //释放写锁
                }
                rwl.readLock().lock(); //然后再上读锁
            }
        }finally{
            rwl.readLock().unlock(); //最后释放读锁
        }
        return value;
    }


}
